/******************************************************************************
 *                  Shanghai ChipON Micro-Electronic Co.,Ltd                  *
 ******************************************************************************
 *  $File Name$       : main.c                                         	      *
 *  $Author$          : ChipON AE/FAE Group                                   *
 *  $Data$            : 2021-12-20                                            *
 *  $AutoSAR Version  : V1.0	                                              *
 *  $Description$     : This file provides the relevant configuration         *
 *                    functions for DMA usart routines		                  *
 ******************************************************************************
 *  Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd                 *
 *  All rights reserved.                                                      *
 *                                                                            *
 *  This software is copyrght protected and proprietary to                    *
 *  Shanghai ChipON Micro-Electronic Co.,Ltd.                                 *
 ******************************************************************************
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
 *                     		REVISON HISTORY                               	  *
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
 *  Data       Version  Author        Description                             *
 *  ~~~~~~~~~~ ~~~~~~~~ ~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
 *  2021-12-20 00.01.00 FAE Group     new creat                               *
 *                                                                            *
 *                                                                            *
 *****************************************************************************/

/******************************************************************************
*                        		Include Files                                 *
******************************************************************************/
#include "system_init.h"
#include "Usart.h"

/******************************************************************************
*                     	Static function declaration                           *
******************************************************************************/
static void Led_Gpio_Init(void);
static void Led_Flip(void);
uint8_t Rx_Flag = 0;

extern uint8_t pre_length;
extern uint8_t *pre_address;
/******************************************************************************
*                        	Structure Definition                              *
******************************************************************************/
Usart_Sdu_Type  Usart_Receive_Sdu = {{0},0};
Usart_Sdu_Type  Usart_Send_Sdu = {{'C','H','I','P',' ','O','N','\r','\n'},10};

/******************************************************************************
*                        	Initialization function                           *
******************************************************************************/
/**
 *  @brief :Initializes the GPIO of the LED
 *  @param in :None
 *  @param out :None
 *  @retval :PF11--LED1
 *  		 PA3 --LED2
 */
static void Led_Gpio_Init(void)
{
	/*Configure the GPIO PA3/PF11 as IO port output mode */
	GPIO_Write_Mode_Bits(GPIOA_SFR, GPIO_PIN_MASK_3 , GPIO_MODE_OUT);
	GPIO_Write_Mode_Bits(GPIOF_SFR, GPIO_PIN_MASK_11 , GPIO_MODE_OUT);
}

/**
 *  @brief :Led flip
 *  @param in :None
 *  @param out :None
 *  @retval :PA3 --LED2
 */
static void Led_Flip(void)
{
	/*Configure the GPIO port PA3 to specify the output data of the pins to be inverted*/
	GPIO_Toggle_Output_Data_Config(GPIOA_SFR, GPIO_PIN_MASK_3);
}

/**
 *  @brief :DMA initialization of Usart
 *  @param in :None
 *  @param out :None
 *  @retval :None
 */
void Usart_Dma_Init(void)
{
	/* Reset the DMA0 peripheral to enable the peripheral clock */
	DMA_Reset(DMA0_SFR);
	/*
	 * DMA0_TX configured as follow:
	 *   - DMA channel selection channel 1
	 *   - Bit width of memory = 8
	 *   - Cyclic mode disable
	 */
	DMA_InitTypeDef DMA_TX_INIT,DMA_RX_INIT;
	DMA_Struct_Init(&DMA_TX_INIT);
	DMA_Struct_Init(&DMA_RX_INIT);
	DMA_TX_INIT.m_Channel = DMA_CHANNEL_1;
	DMA_TX_INIT.m_Direction = DMA_MEMORY_TO_PERIPHERAL;
	DMA_TX_INIT.m_PeripheralDataSize = DMA_DATA_WIDTH_8_BITS;
	DMA_TX_INIT.m_MemoryDataSize = DMA_DATA_WIDTH_8_BITS;
	DMA_TX_INIT.m_Priority = DMA_CHANNEL_LOWER;
	DMA_TX_INIT.m_PeripheralInc = FALSE;
	DMA_TX_INIT.m_MemoryInc = TRUE;
	DMA_TX_INIT.m_LoopMode = FALSE;
	DMA_TX_INIT.m_BlockMode = DMA_TRANSFER_BYTE;
	DMA_TX_INIT.m_MemoryAddr = (uint32_t)0;
	DMA_TX_INIT.m_PeriphAddr = (uint32_t)&(USART0_SFR->TBUFR);
	DMA_Configuration(DMA0_SFR,&DMA_TX_INIT);
	/*
	 * DMA0_RX configured as follow:
	 *   - DMA channel selection channel 2
	 *   - Bit width of memory = 8
	 *   - Number of data transmitted = 100
	 *   - Cyclic mode disable
	 */
	DMA_RX_INIT.m_Channel = DMA_CHANNEL_2;
	DMA_RX_INIT.m_Direction = DMA_PERIPHERAL_TO_MEMORY;
	DMA_RX_INIT.m_PeripheralDataSize = DMA_DATA_WIDTH_8_BITS;
	DMA_RX_INIT.m_MemoryDataSize = DMA_DATA_WIDTH_8_BITS;
	DMA_RX_INIT.m_Priority = DMA_CHANNEL_LOWER;
	DMA_RX_INIT.m_Number = 100;
	DMA_RX_INIT.m_PeripheralInc = FALSE;
	DMA_RX_INIT.m_MemoryInc = TRUE;
	DMA_RX_INIT.m_LoopMode = TRUE;
	DMA_RX_INIT.m_BlockMode = DMA_TRANSFER_BYTE;
	DMA_RX_INIT.m_PeriphAddr = (uint32_t)&(USART0_SFR->RBUFR);
	DMA_RX_INIT.m_MemoryAddr = (uint32_t)&Usart_Receive_Sdu.Data[0];
	DMA_Configuration(DMA0_SFR,&DMA_RX_INIT);
}

/**
 *  @brief :USART transfers data using DMA
 *  @param in : pData : Memory first address
 *  			nSize : Length of Data sent
 *  @param out :None
 *  @retval :None
 */
void UartDMATransmit(uint8_t *pData,uint16_t nSize)
{
	DMA_Memory_Start_Address_Config(DMA0_SFR, DMA_CHANNEL_1,(uint32_t)pData);
	DMA_Transfer_Number_Config(DMA0_SFR, DMA_CHANNEL_1,nSize);
	USART_Transmit_Data_Enable(USART0_SFR,TRUE);
	DMA_Channel_Enable (DMA0_SFR, DMA_CHANNEL_1, TRUE);
}

/**
 *  @brief :USART receives data processing functions
 *  @param in : None
 *  @param out :None
 *  @retval :None
 */
void Receiving_data_processing(void)
{
	/* Determines whether the data spans the end of the array */
	if(Usart_Receive_Sdu.Length < pre_length)
	{
		/* If spanned, segmented output data */
		UartDMATransmit(pre_address,100 - pre_length);
		systick_delay_ms(5);
		UartDMATransmit(Usart_Receive_Sdu.Data,Usart_Receive_Sdu.Length);
	}else
	{
		/* Direct output */
		UartDMATransmit(pre_address,Usart_Receive_Sdu.Length - pre_length);
	}

	systick_delay_ms(10);
	memset(Usart_Receive_Sdu.Data, 0, Usart_Receive_Sdu.Length+2);
	pre_length = Usart_Receive_Sdu.Length;
	pre_address = Usart_Receive_Sdu.Data + Usart_Receive_Sdu.Length;
}

int main()
{
	/* Initialize the system clock is 72M*/
	SystemInit(72);
	/* Setup SysTick Timer as delay function */
	systick_delay_init(72);
	/*
	 * Initialize led IOs
	 * Configure the GPIO PA4/PD12/PF7/PH3 as IO port output mode
	 */
	Led_Gpio_Init();
	/*
	 *  Set Usart Tx and Rx PINS
	 *  PA3 -- USART0_TX0
	 *      - Configure PA3 remap mode
     *      - Push�Cpull output
	 *  PE7 -- USART0_RX
	 *      - Configure PE7 remap mode
	 *      - Configured in pull-up mode
	 */
	Usart_Gpio_Init();
	/*
	 *  Set Usart DMA as follow:
	 *  DMA_TX:
	 *     Channel = DMA_CHANNEL_1;
	 *     Direction = DMA_MEMORY_TO_PERIPHERAL;
	 *     PeripheralDataSize = 8 Bits;
	 *     MemoryDataSize = 8 Bits;
	 *     Number of data transmitted = 8;
	 *  DMA_RX:
	 *     Channel = DMA_CHANNEL_2;
	 *     Direction = DMA_PERIPHERAL_TO_MEMORY;
	 *     PeripheralDataSize = 8 Bits;
	 *     MemoryDataSize = 8 Bits;
	 *     Number of data transmitted = 8;
	 */
	Usart_Dma_Init();
	/*
	 *  Set Usart0 working mode :
	 *    - Set Usart0 to async mode
	 *    - Set baudrate to 115200
	 *    - Configuring DMA Channel 1/ Channel 2 enable
	 *    - Set up a DMA read serial port to receive the data register to enable
	 *    - Set up DMA write serial port to send data register enable
	 */
	USART_Mode_Config(USART0_SFR);
	/* Idle interrupt enable */
	USART_Int_Config(USART0_SFR, INT_USART0);
	/*Sending data to initiate DMA/n */
	USART_SendData(USART0_SFR, 0);

	INT_All_Enable(TRUE);

	/* Tag address initialization */
	pre_address = Usart_Receive_Sdu.Data;
	/* Tag length initialization */
	pre_length = 0;

	while(1)
	{
		/* If Rx_Flag is 1*/
		if(Rx_Flag == 1)
		{
			/* Set Rx_Flag to 0 */
			Rx_Flag = 0;
			/* Led1 flip */
			GPIO_Toggle_Output_Data_Config(GPIOD_SFR, GPIO_PIN_MASK_12);
			Receiving_data_processing();
		}else
		{
		}
		systick_delay_ms(250);
		systick_delay_ms(250);
		Led_Flip();
	}		
}
